import { inject, type VNodeChild } from 'vue';
import type { CreateToasterReturn } from '@ark-ui/vue/toast';
import { toastInjectionKey } from '../utils/keys';

type Type = 'success' | 'error' | 'loading' | 'info' | (string & {});
type Placement = 'top-start' | 'top' | 'top-end' | 'bottom-start' | 'bottom' | 'bottom-end';
type Status = 'visible' | 'dismissing' | 'unmounted';

interface StatusChangeDetails {
  status: Status;
}

interface ActionOptions {
  /**
   * The label of the action
   */
  label: string;
  /**
   * The function to call when the action is clicked
   */
  onClick: () => void;
}

interface Options {
  /**
   * The title of the toast.
   */
  title?: VNodeChild | undefined;
  /**
   * The description of the toast.
   */
  description?: VNodeChild | undefined;

  /**
   * The duration the toast will be visible
   */
  duration?: number | undefined;
  /**
   * The duration for the toast to kept alive before it is removed.
   * Useful for exit transitions.
   */
  removeDelay?: number | undefined;
  /**
   * The placement of the toast
   */
  placement?: Placement | undefined;
  /**
   * The unique id of the toast
   */
  id?: string | undefined;
  /**
   * The type of the toast
   */
  type?: Type | undefined;
  /**
   * Function called when the toast is visible
   */
  onStatusChange?(details: StatusChangeDetails): void;
  /**
   * The action of the toast
   */
  action?: ActionOptions | undefined;
  /**
   * The metadata of the toast
   */
  meta?: Record<string, any> | undefined;
}

export function useToast() {
  let toaster: CreateToasterReturn | null | undefined = null;

  if (!import.meta.env.SSR) {
    toaster = inject(toastInjectionKey);
  }
  else {
    toaster = null;
  }

  return {
    toaster,

    create: (options: Options) => {
      if (toaster) {
        return toaster.create(options);
      }
    },

    success: (options: Options | string | undefined) => {
      if (toaster && options) {
        if (typeof options === 'string') {
          return toaster.success({ description: options });
        }

        return toaster.success(options);
      }
    },

    error: (options: Options | string | undefined) => {
      if (toaster && options) {
        if (typeof options === 'string') {
          return toaster.error({ description: options });
        }

        return toaster.error(options);
      }
    },
  };
}
